﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="TaskScheduler.cs" company="JDML Consulting Ltd.">
//   Copyright 2011 Photon Project - http://photon.codeplex.com
// </copyright>
// <summary>
//   Defines the TaskScheduler type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Photon.Threading
{
    using System;

    public class TaskScheduler
    {
        #region Fields

        private readonly ITaskDispatcher _dispatcher;
        private readonly ITaskDispatcher _asyncDispatcher;
        private static TaskScheduler _synchronous;
        private static TaskScheduler _default;

        #endregion

        public TaskScheduler(ITaskDispatcher dispather, ITaskDispatcher asyncDispatcher)
        {
            _dispatcher = Guard.ArgumentNull("dispatcher", dispather);
            _asyncDispatcher = Guard.ArgumentNull("asyncDispatcher", asyncDispatcher);
        }

        public static TaskScheduler ForCurrentSynchronizationContext()
        {
            var ctxDispatcher = Dispatcher.FromCurrentSynchronizationContext();
            return new TaskScheduler(
                  new TaskDispatcher(ctxDispatcher, Dispatcher.Synchronous),
                  new TaskDispatcher(Dispatcher.Synchronous, ctxDispatcher));
        }

        public static TaskScheduler ForUISendAndReceive()
        {
            var uiDispatcher = Dispatcher.FromCurrentUIContext();
            return new TaskScheduler(
                  new TaskDispatcher(uiDispatcher, uiDispatcher),
                  new TaskDispatcher(Dispatcher.Synchronous, uiDispatcher));
        }

        public static TaskScheduler ForUIReceive()
        {
            var uiDispatcher = Dispatcher.FromCurrentUIContext();
            return new TaskScheduler(
                  new TaskDispatcher(Dispatcher.ThreadPool, uiDispatcher),
                  new TaskDispatcher(Dispatcher.Synchronous, uiDispatcher));
        }

        public static TaskScheduler ForUISend()
        {
            var uiDispatcher = Dispatcher.FromCurrentUIContext();
            return new TaskScheduler(
                  new TaskDispatcher(uiDispatcher, Dispatcher.Synchronous),
                  new TaskDispatcher(Dispatcher.Synchronous, Dispatcher.Synchronous));
        }

        public static TaskScheduler Default
        {
            get
            {
                return _default ?? (_default = new TaskScheduler(
                    new TaskDispatcher(Dispatcher.ThreadPool, Dispatcher.Synchronous),
                    new TaskDispatcher(Dispatcher.Synchronous, Dispatcher.Synchronous)));
            }
        }

        public static TaskScheduler Synchronous
        {
            get
            {
                if (_synchronous == null)
                {
                    _synchronous = new TaskScheduler(
                       new TaskDispatcher(Dispatcher.Synchronous, Dispatcher.Synchronous),
                       new TaskDispatcher(Dispatcher.Synchronous, Dispatcher.Synchronous));
                }
                return _synchronous;
            }
        }

        internal void QueueInvoke(Action action)
        {
            _dispatcher.BeginInvoke(action);
        }

        internal void QueueReturn(Action action)
        {
            _dispatcher.BeginReturn(action);
        }

        internal void QueueAsyncInvoke(Action action)
        {
            _asyncDispatcher.BeginInvoke(action);
        }

        internal void QueueAsyncReturn(Action action)
        {
            _asyncDispatcher.BeginReturn(action);
        }
    }
}
